package com.jfinal.plugin.sqlxml;

import com.jfinal.log.Logger;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.regex.Pattern;
import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 把xml变成bean的类
 *
 * @author tangyang
 */
public class XmlDaoBeanCreator {

    static final Logger logger = Logger.getLogger(XmlDaoBeanCreator.class);

    static Pattern allPattern = Pattern.compile("\\$\\{(.+?)\\}|\\#\\{(.+?)\\}");
    static Pattern argsPattern = Pattern.compile("\\$\\{(.*?)\\}");

    static Pattern stringPattern = Pattern.compile("\\#\\{(.*?)\\}");

    static final String TAG_FOR_CLASS = "for-class";
    static final String TAG_SELECT = "select";

    static final String ATTR_ACTION = "action";
    static final String ATTR_PARAS = "paras";
    static final String TAG_USE_PAGE = "use-page";
    static final String TAG_IF = "if";
    static final String TAG_EXCEPTION = "exception";
    static final String TAG_UPDATE = "update";
    static final ClassPool CLASS_POOL = ClassPool.getDefault();
    static final String SQL_OBJ_LIST_STR = "$objList";

    static {
        ClassClassPath classPath = new ClassClassPath(XmlDaoBeanCreator.class);
        CLASS_POOL.insertClassPath(classPath);
    }
    CtClass currentInterface;
    Class orignalInterface;
    CtClass theClass;
    Method[] methods;

    public void xmlToBean(Document document) {

        NodeList forClassList = document.getElementsByTagName(TAG_FOR_CLASS);
        if (forClassList.getLength() < 1) {
            throw new SqlXmlException("Need for-class tag!");
        }
        String className = forClassList.item(0).getTextContent();
        try {
            orignalInterface = Class.forName(className);

        } catch (ClassNotFoundException ex) {
            logger.error("Your class not found.", ex);
        }
        if (SqlXmlPlugin.debug) {
            logger.info("start create class for " + className);
        }
        try {
            currentInterface = CLASS_POOL.get(className);
            methods = orignalInterface.getDeclaredMethods();
        } catch (NotFoundException ex) {
            throw new SqlXmlException(ex);
        }
        theClass = CLASS_POOL.makeClass(className + "ImplBySqlXml");
        theClass.setInterfaces(new CtClass[]{currentInterface});

        NodeList selectList = document.getElementsByTagName(TAG_SELECT);
        int selLen = selectList.getLength();
        for (int i = 0; i < selLen; i++) {
            if (SqlXmlPlugin.debug) {
                logger.info(" create select  methods... ");
            }
            Node node = selectList.item(i);
            MethodCreator methodCreator = new MethodCreator(
                    currentInterface, orignalInterface, theClass, methods, node);
            methodCreator.startCreateMethod();
        }
        NodeList updateList = document.getElementsByTagName(TAG_UPDATE);
        int updateLen = updateList.getLength();
        for (int i = 0; i < updateLen; i++) {
            Node node = updateList.item(i);
            MethodCreator methodCreator = new MethodCreator(
                    currentInterface, orignalInterface, theClass, methods, node);
            methodCreator.startCreateMethod(MethodCreator.mtype.UPDATE);
        }
        try {

            Class toClass = theClass.toClass();
            SQLDaoContainer.put(orignalInterface, toClass.newInstance());
        } catch (CannotCompileException ex) {
            throw new SqlXmlException("I dont know.", ex);
        } catch (InstantiationException ex) {
            throw new SqlXmlException("I dont know.", ex);
        } catch (IllegalAccessException ex) {
            throw new SqlXmlException("I dont know.", ex);

        }
    }

}
